import tkinter as tk
from tkinter import ttk, messagebox
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import pandas as pd
import requests
from bs4 import BeautifulSoup
from pip._internal.utils import logging
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
import time
from selenium.webdriver.common.action_chains import ActionChains

# 配置ChromeOptions，设置detach为True，使浏览器窗口不会自动关闭
chrome_options = webdriver.ChromeOptions()
chrome_options.add_experimental_option("detach", True)

# 指定chromedriver的实际路径
chromedriver_path = r'C:\Program Files\Google\Chrome\Application\chromedriver.exe'
service = Service(executable_path=chromedriver_path)

# 创建Chrome浏览器实例
driver = webdriver.Chrome(options=chrome_options, service=service)


# 爬虫相关的功能
def start_crawling():
    global all_data  # 声明all_data为全局变量
    names = ["2024年11月", "2024年10月", "2024年09月", "2024年08月", "2024年07月", "2024年06月"]
    all_data = []  # 清空之前的所有数据
    driver.get("https://www.dongchedi.com/sales")  # 打开懂车帝页面

    body_element = driver.find_element(By.TAG_NAME, "body")
    # 向下滚动界面
    def down():
        for i in range(0, 300):
            body_element.send_keys(Keys.DOWN)

    def get_html_from_url():
        html = driver.page_source
        return html

    def parse_single_html(html):
        hash_sale = {}
        soup = BeautifulSoup(html, 'html.parser')
        cars = (soup.find("div", class_="jsx-495096444 tw-col-span-5")).find_all("li", class_="list_item__3gOKl")
        datas = []
        for i in range(0, 50):
            car = cars[i]
            car_name = car.find("a", class_="tw-font-semibold").get_text()
            car_type = car.find("span", class_="tw-text-12 tw-text-color-gray-700 tw-ml-6").get_text()
            car_sale_price = car.find("p", class_="tw-leading-22 tw-text-color-red-500 tw-font-semibold").get_text()
            car_sale_count = car.find("p", class_="tw-text-18 tw-font-semibold tw-leading-28").get_text()
            car_sale_count = car_sale_count.replace(",", "")
            car_com = car_type.split("/")[0]
            if car_com not in hash_sale:
                hash_sale[car_com] = int(car_sale_count)
            else:
                hash_sale[car_com] += int(car_sale_count)
            datas.append({
                "排名": (i + 1),
                "车名": car_name,
                "品牌/车型": car_type,
                "价格": car_sale_price,
                "本月销量": car_sale_count
            })
        return datas

    # 点击切换月份
    def click(name):
        button = driver.find_element(By.CSS_SELECTOR, ".tw-relative.more_item__2UARp")
        actions = ActionChains(driver)
        actions.move_to_element(button)
        actions.perform()  # 执行构建好的鼠标动作链，实现鼠标悬停效果
        button2 = driver.find_elements(By.CSS_SELECTOR, "a.more_option___6xpL")
        for b in button2:
            element_text = b.text  # 获取元素的文本内容
            if element_text == name:
                b.click()  # 如果文本内容符合要求，点击该按钮

    selected_month = selected_month_var.get()  # 获取用户选择的月份
    click(selected_month)  # 只点击用户选择的月份
    down()  # 向下滚动界面
    html = get_html_from_url()  # 获取页面的HTML
    datas = parse_single_html(html)  # 解析HTML
    all_data.extend(datas)  # 将数据添加到all_data中

    display_data(all_data)

# 更新表格显示数据
def display_data(datas):
    # 清空Treeview
    for row in treeview.get_children():
        treeview.delete(row)

    # 在Treeview中显示数据
    for data in datas:
        treeview.insert("", "end", values=(data["排名"], data["车名"], data["品牌/车型"], data["价格"], data["本月销量"]))

# 生成柱状图
def plot_bar_chart():
    global all_data  # 确保使用全局变量
    # 清除之前的图表
    for widget in chart_display_frame.winfo_children():
        widget.destroy()

    # 数据处理
    car_names = [data["车名"] for data in all_data]
    sale_counts = [int(data["本月销量"]) for data in all_data]

    # 创建柱状图
    fig = plt.figure(figsize=(10, 6))  # 设定图表大小
    plt.barh(car_names, sale_counts, color='skyblue')
    plt.xlabel('本月销量')
    plt.title('汽车销量柱状图')
    plt.tight_layout()

    # 在Tkinter中显示图表
    canvas_agg = FigureCanvasTkAgg(fig, master=chart_display_frame)
    canvas_agg.get_tk_widget().pack(pady=10, fill=tk.BOTH, expand=True)
    canvas_agg.draw()

# 生成扇形图
def plot_pie_chart():
    global all_data  # 确保使用全局变量
    # 清除之前的图表
    for widget in chart_display_frame.winfo_children():
        widget.destroy()

    # 数据处理
    car_names = [data["车名"] for data in all_data]
    sale_counts = [int(data["本月销量"]) for data in all_data]

    # 创建扇形图
    fig = plt.figure(figsize=(8, 8))  # 设定图表大小
    plt.pie(sale_counts, labels=car_names, autopct='%1.1f%%', startangle=140)
    plt.title('汽车销量扇形图')

    # 在Tkinter中显示图表
    canvas_agg = FigureCanvasTkAgg(fig, master=chart_display_frame)
    canvas_agg.get_tk_widget().pack(pady=10, fill=tk.BOTH, expand=True)
    canvas_agg.draw()

# 创建主窗口
root = tk.Tk()
root.title("懂车帝销量数据爬虫")
root.geometry("900x750")

# 获取屏幕的宽度和高度
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()

# 设置窗口的位置，使其显示在屏幕的右侧
window_width = 950
window_height = 780
x_position = screen_width - window_width  # 设置x坐标为屏幕右侧
y_position = (screen_height - window_height) // 2  # 垂直居中

# 设置窗口的位置和大小
root.geometry(f"{window_width}x{window_height}+{x_position}+{y_position}")

# 创建Notebook (选项卡)
notebook = ttk.Notebook(root)
notebook.pack(pady=10, fill=tk.BOTH, expand=True)

# 创建表格Tab
table_tab = ttk.Frame(notebook)
notebook.add(table_tab, text="销量数据")

# 创建图表Tab
chart_tab = ttk.Frame(notebook)
notebook.add(chart_tab, text="图表展示")

# 在表格Tab中创建Treeview显示数据
columns = ("排名", "车名", "品牌/车型", "价格", "本月销量")
treeview_frame = tk.Frame(table_tab)
treeview_frame.pack(pady=10, padx=10, fill=tk.BOTH, expand=True)

treeview_scrollbar = tk.Scrollbar(treeview_frame, orient=tk.VERTICAL)
treeview = ttk.Treeview(treeview_frame, columns=columns, show="headings", height=15, yscrollcommand=treeview_scrollbar.set)

for col in columns:
    treeview.heading(col, text=col)
    treeview.column(col, width=150, anchor="center")

treeview_scrollbar.config(command=treeview.yview)
treeview_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
treeview.pack(pady=10, padx=10, fill=tk.BOTH, expand=True)

# 在图表Tab中创建一个框架来放置图表
chart_display_frame = tk.Frame(chart_tab)
chart_display_frame.pack(pady=10, padx=10, fill=tk.BOTH, expand=True)

# 在图表Tab中创建一个框架来放置按钮
button_frame = tk.Frame(chart_tab)
button_frame.pack(pady=10)

# 创建月份选择下拉框
months = ["2024年11月", "2024年10月", "2024年09月", "2024年08月", "2024年07月", "2024年06月"]
selected_month_var = tk.StringVar()
selected_month_var.set(months[0])  # 默认选择第一个月份

month_menu = tk.OptionMenu(table_tab, selected_month_var, *months)
month_menu.pack(pady=10)

# 创建开始爬取按钮
crawl_button = tk.Button(table_tab, text="开始爬取", command=start_crawling)
crawl_button.pack(pady=10)

# 创建生成柱状图按钮
bar_button = tk.Button(button_frame, text="生成柱状图", command=plot_bar_chart)
bar_button.pack(pady=5)

# 创建生成扇形图按钮
pie_button = tk.Button(button_frame, text="生成扇形图", command=plot_pie_chart)
pie_button.pack(pady=5)

# 运行主循环
root.mainloop()